package com.igame.Service.impl;

import com.igame.Service.CodeService;
import com.igame.Service.CommonService;
import com.igame.Service.UserService;
import com.igame.Utils.AreaHierarchyBuilder;
import com.igame.Utils.JwtUtil;
import com.igame.common.Result;
import com.igame.common.service.RedisUserService;
import com.igame.constant.UserConstant;
import com.igame.dto.*;
import com.igame.entity.*;
import com.igame.mapper.UserMapper;
import com.igame.vo.UserVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDate;
import java.time.Period;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service
public class UserServiceImpl  implements UserService, RedisUserService{
    @Autowired
    UserMapper userMapper;

    @Autowired
    CodeService codeService;


    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private RedisTemplate<String, User> redisTemplate;

    @Autowired
    private CommonService commonService;
    @Override
    @Transactional
    public Result Register(UserDto userDto) {
        User user = new User();
        BeanUtils.copyProperties(userDto, user);
        // 计算用户年龄并设置
        LocalDate userDtoBirth = userDto.getBirth();
        LocalDate now = LocalDate.now();
        Period period = Period.between(userDtoBirth, now);
        user.setAge(period.getYears());
//        设置用户状态
        user.setState(UserConstant.InUse);
//        加密密码
        user.setPassword(passwordEncoder.encode(user.getPassword()));
//        设置用户角色 为普通用户
        user.setRole(UserConstant.Normal);
        user.setAvatarPath(UserConstant.defaultAvatar);
        user.setCreateTime(LocalDate.now());
        User userByEmail = userMapper.findUserByEmail(user.getEmail());
        User userName = userMapper.selectByUserName(user.getUsername());
        Result result = new Result();
        try {

            String codeValue = codeService.getCode("code");

            if (userByEmail != null) {
                throw new RuntimeException("邮箱已注册，请直接登录");
            } else if (userName != null) {
                throw new RuntimeException("用户名已存在");
            } else if (codeValue == null) {
                throw new RuntimeException("验证码已过期(有效期3分钟),请刷新验证码");
            } else if (!userDto.getCaptcha().equals(codeValue)) {
                throw new RuntimeException("验证码输入错误");
            }
            int insertNum = userMapper.insert(user);
            if (insertNum == 0) {
                throw new RuntimeException("数据插入失败，请稍后再试");
            }

            result.setState(true);
            result.setErrMessage(null);
        } catch (Exception e) {
            // 发生异常时回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            result.setState(false);
            result.setErrMessage(e.getMessage());
        }
        return result;
    }

    @Override
    @Transactional
    public Result<User> login(UserDto userDto) {
        Result<User> result = new Result<>();
        try {
            // 验证用户身份
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(userDto.getUsername(), userDto.getPassword())
            );
            // 生成JWT令牌
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            String token = jwtUtil.generateToken(userDetails.getUsername());
            // 设置返回结果
            User getUser = userMapper.selectByUserName(userDto.getUsername());
            result.setState(true);
            result.setErrMessage(null);
            result.setData(getUser);
            result.setToken(token); // 返回令牌
            // 将用户信息存储到Redis
            storeUserInRedis(getUser);

        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            result.setState(false);
            result.setErrMessage(e.getMessage());
            result.setData(null);
        }
        return result;
    }
    @Override
    public void storeUserInRedis(User user) {
        redisTemplate.opsForValue().set("user:" + user.getUsername(), user, 1, TimeUnit.HOURS);
    }

    @Override
    public User getUserFromRedis(String username) {
        return redisTemplate.opsForValue().get("user:" + username);
    }


    @Override
    public Result<UserVo> getUserById(Integer id) {

        User user = userMapper.selectUserById(id);
        String caret = extractBeforeCaret(user.getAddress());
        UserVo userVo =new UserVo();
        BeanUtils.copyProperties(user,userVo);
        userVo.setAddress(caret);
        LocalDate userDtoBirth = user.getCreateTime();
        LocalDate now = LocalDate.now();
        Period period = Period.between(userDtoBirth, now);
        userVo.setAccountAge(period.getYears());
        return Result.success(userVo);
    }

    @Override
    public AreaResponse getAllArea() {
        List<AreaInfo> allAreas = userMapper.getAllArea();
        AreaHierarchyBuilder builder = new AreaHierarchyBuilder(allAreas);
        AreaResponse response = new AreaResponse();
        List<Province> provinces = builder.getProvinces().stream().map(provinceInfo -> {
            Province province = new Province();
            province.setCode(provinceInfo.getAreaCode());
            province.setName(provinceInfo.getAreaName());
            province.setCities(builder.getCities(provinceInfo.getAreaCode()).stream().map(cityInfo -> {
                City city = new City();
                city.setCode(cityInfo.getAreaCode());
                city.setName(cityInfo.getAreaName());
                city.setDistricts(builder.getDistricts(cityInfo.getAreaCode()).stream().map(districtInfo -> {
                    District district = new District();
                    district.setCode(districtInfo.getAreaCode());
                    district.setName(districtInfo.getAreaName());
                    return district;
                }).collect(Collectors.toList()));
                return city;
            }).collect(Collectors.toList()));
            return province;
        }).collect(Collectors.toList());

        response.setProvinces(provinces);
        return response;
    }

    @Override
    @Transactional
    public Result update(Integer id, String username, String provinceName, String cityName, String districtName, String address, MultipartFile file) {
            User user = new User();
            try {
                String userNameIsExist = userMapper.userNameIsExist(id, username);
                if (userNameIsExist!=null){
                    throw new RuntimeException("该用户名已存在");
                }
                user.setId(id);
                user.setUsername(username);
                if (!provinceName.equals("未选择省") && !cityName.equals("未选择市") && !districtName.equals("未选择区/县") && !address.equals("未填写详细地址")){
                    user.setAddress(provinceName+cityName+districtName+"^"+address);
                }
                if (file!=null){
                    String upload = commonService.upload(file);
                    user.setAvatarPath(upload);
                }
                userMapper.updateUser(user);
                return Result.success(user);
            }catch (Exception e){
                return Result.error(e.getMessage());
            }

    }

    @Override
    public Result verifyPassword(UserDto userDto) {
        // 从数据库中根据用户ID获取用户信息
        User user = userMapper.selectUserById(userDto.getId());

        // 检查用户是否存在
        if (user == null) {
            return Result.error("用户不存在");
        }
        // 使用passwordEncoder的matches方法来验证密码
        boolean isPasswordValid = passwordEncoder.matches(userDto.getPassword(), user.getPassword());
        if (isPasswordValid) {
            return Result.success("密码验证成功");
        } else {
            return Result.error("密码错误");
        }
    }

//添加密保
    @Override
    public Result addPasswordSecurity(SecurityQuestionsRequestDTO request) {
        int security=0;
        for (int i = 0; i < request.getQuestions().size(); i++) {
            PasswordSecurity passwordSecurity =new PasswordSecurity();
            passwordSecurity.setUserId(request.getId());
            passwordSecurity.setAnswer(request.getQuestions().get(i).getAnswer());
            passwordSecurity.setQuestion(request.getQuestions().get(i).getQuestion());
             security = userMapper.insertPasswordSecurity(passwordSecurity);
        }
        if (security>0){
            return Result.success();
        }
        return Result.error("设置密保失败");
    }

    @Override
    public Result<List<PasswordSecurity>> userHavePds(Integer userId) {
        List<PasswordSecurity> passwordSecurities = userMapper.userHavePds(userId);
        if (passwordSecurities!=null){
            return Result.success(passwordSecurities);
        }
        return Result.error("该用户还没设置密保");
    }

    @Override
    public Result changePassword(ChangePasswordDto changePasswordDto) {

        changePasswordDto.setNewPassword(passwordEncoder.encode(changePasswordDto.getNewPassword()));

        int i = userMapper.updatePassword(changePasswordDto);
        if (i>0){
            return Result.success();
        }
        return Result.error("修改密码失败");
    }

    @Override
    public Result<String> sendCode(String email) {
        User user = userMapper.findUserByEmail(email.replace("\"", ""));
        if (user!=null){
            // 创建一个Random对象
            Random random = new Random();
            // 生成一个6位的随机数
            int code = 100000 + random.nextInt(900000); // 生成100000到999999之间的随机数

            // 将随机数转换为字符串
            String codeString = Integer.toString(code);
            return Result.success(codeString);
        }
        return Result.error("该账户邮箱没绑定账户");
    }

    @Override
    public Result forgotPassword(ChangePasswordDto changePasswordDto) {
        changePasswordDto.setNewPassword(passwordEncoder.encode(changePasswordDto.getNewPassword()));
        int i = userMapper.updatePasswordByEmail(changePasswordDto);
        if (i>0){
            return Result.success();
        }
        return Result.error("修改密码失败");
    }

    @Override
    public Result<List<PasswordSecurity>> getPasswordSecurity(String username) {
        Integer id = userMapper.selectByIdName(username.replace("\"", ""));
        if (id!=null){
            List<PasswordSecurity> passwordSecurities = userMapper.userHavePds(id);
            return Result.success(passwordSecurities);
        }
        return Result.error("不存在该用户或用户没有设置密保");
    }


    @Override
    public Result<String> getAvatarByUserName(String username) {
        return Result.success(userMapper.selectAvatarByUserName(username));
    }

    @Override
    public Result<UserVo> getUpUser(String username) {
        User user = userMapper.selectByUserName(username);
        extractBeforeCaret(user.getAddress());
        UserVo userVo =new UserVo();
        BeanUtils.copyProperties(user,userVo);
        userVo.setAddress(extractBeforeCaret(user.getAddress()));
        LocalDate userDtoBirth = user.getCreateTime();
        LocalDate now = LocalDate.now();
        Period period = Period.between(userDtoBirth, now);
        userVo.setAccountAge(period.getYears());
        return Result.success(userVo);
    }
// 添加关注的人
    @Override
    @Transactional
    public Result addFollow(FollowDto followDto) {
        Follow follow =new Follow();
        Result result =new Result();
        boolean isSelf = followDto.getUserId() ==followDto.getFollowUser();
        try {
            Follow isFollow = userMapper.isFollow(followDto);
            BeanUtils.copyProperties(followDto,follow);
            int i = userMapper.insertFollow(follow);
            if (i==0){
                throw new RuntimeException("添加失败请稍后再试");
            } else if (isSelf) {
                throw new RuntimeException("您时刻在关注自己哦");
            } else if (isFollow!=null) {
                throw new RuntimeException("已经关注过啦!");
            }
            result.setState(true);
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            result.setState(false);
            result.setErrMessage(e.getMessage());
        }
        return result ;
    }

    @Override
    public Integer getIdByName(String userName) {
        return userMapper.selectByIdName(userName);
    }

    @Override
    public Result<Set<String>> getUserNameById(List<Integer> idList) {
        Set<String> userNames = new HashSet<>();
        // 遍历每个 ID 并从数据库中获取用户名
        for (Integer id : idList) {
            String userName = userMapper.selectUserNameById(id);
            if (userName != null) {
                userNames.add(userName);
            }
        }
        // 创建 Result 对象并返回
        return Result.success(userNames);
    }

    // 利用特殊符号做分割
    public static String extractBeforeCaret(String str) {
        // 查找^符号的位置
        int index = str.indexOf('^');
        if (index != -1) {
            // 提取^符号前的子串
            return str.substring(0, index).trim();
        }
        // 如果没有找到^符号，则返回原始字符串
        return str;
    }

    // 去除特殊符号
    public static String removeCaret(String str) {
        // 替换掉所有的^符号
        return str.replace("^", "").trim();
    }
}
